home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1995 June / MacFormat 25.iso / Shareware City / Developers / OutOfPhase1.1 Source / OutOfPhase Folder / OscBankPlayer.c < prev    next >
Text File  |  1994-12-10  |  30KB  |  880 lines

  1. /* OscBankPlayer.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #define ShowMeFrozenNoteRec
  31. #define ShowMe_NoteObjectRec
  32. #include "OscBankPlayer.h"
  33. #include "LFOGenerator.h"
  34. #include "IncrementalParameterUpdator.h"
  35. #include "LFOSpecifier.h"
  36. #include "LFOListSpecifier.h"
  37. #include "Memory.h"
  38. #include "Array.h"
  39. #include "OscillatorListSpecifier.h"
  40. #include "OscillatorSpecifier.h"
  41. #include "InstrumentStructure.h"
  42. #include "SampleOscControl.h"
  43. #include "WaveTableOscControl.h"
  44. #include "DeterminedNoteStructure.h"
  45. #include "NoteObject.h"
  46. #include "FloatingPoint.h"
  47. #include "Frequency.h"
  48. #include "ErrorDaemon.h"
  49.  
  50.  
  51. typedef struct
  52.     {
  53.         /* this is the reference to the template object */
  54.         void*                                        TemplateReference;
  55.  
  56.         /* perform one envelope update cycle */
  57.         void                                        (*UpdateEnvelopes)(void* State);
  58.         /* dispose of the state record */
  59.         void                                        (*DisposeState)(void* State);
  60.         /* dispose of the information template */
  61.         void                                        (*DisposeTemplate)(void* Template);
  62.         /* create a new state object. */
  63.         void*                                        (*NewState)(void* Template,
  64.                                                             float FreqForMultisampling, float Accent1, float Accent2,
  65.                                                             float Accent3, float Accent4, float Loudness, float HurryUp,
  66.                                                             long* PreOriginTimeOut, float StereoPosition,
  67.                                                             float InitialFrequency, float PitchDisplacementDepthLimit,
  68.                                                             float PitchDisplacementRateLimit,
  69.                                                             long PitchDisplacementStartPoint);
  70.         /* fix up pre-origin time for the state object */
  71.         void                                        (*FixUpStatePreOrigin)(void* State, long ActualPreOrigin);
  72.         /* set a new frequency for a state object.  used for portamento */
  73.         /* and modulation of frequency (vibrato) */
  74.         void                                        (*StateNewFrequency)(void* State, float NewFrequencyHertz);
  75.         /* send a key-up signal to one of the oscillators */
  76.         void                                        (*KeyUpSustain1)(void* State);
  77.         void                                        (*KeyUpSustain2)(void* State);
  78.         void                                        (*KeyUpSustain3)(void* State);
  79.         /* restart a oscillator.  this is used for tie continuations */
  80.         void                                        (*RestartState)(void* State, float NewFreqMultisampling,
  81.                                                             float NewAccent1, float NewAccent2, float NewAccent3,
  82.                                                             float NewAccent4, float NewLoudness, float NewHurryUp,
  83.                                                             MyBoolean RetriggerEnvelopes, float NewStereoPosition,
  84.                                                             float NewInitialFrequency,
  85.                                                             float PitchDisplacementDepthLimit,
  86.                                                             float PitchDisplacementRateLimit,
  87.                                                             long PitchDisplacementStartPoint);
  88.         /* generate a sequence of samples (called for each envelope clock) */
  89.         void                                        (*GenSamples)(void* State, long SampleCount,
  90.                                                             largefixedsigned* RawBuffer);
  91.         /* find out if the oscillator has finished yet */
  92.         MyBoolean                                (*IsItFinished)(void* State);
  93.     } OscBankVectorRec;
  94.  
  95.  
  96. struct OscBankTemplateRec
  97.     {
  98.         /* general parameters */
  99.         MyBoolean                                StereoOutput;
  100.         float                                        OverallVolumeScalingFactor;
  101.         long                                        SamplingRate;
  102.         float                                        EnvelopeUpdateRate;
  103.         MyBoolean                                TimeInterpolation;
  104.         MyBoolean                                WaveInterpolation;
  105.  
  106.         /* parameter updator for track (so we can set up individual notes properly) */
  107.         IncrParamUpdateRec*            ParamUpdator;
  108.  
  109.         /* template for the pitch displacement LFO */
  110.         LFOListSpecRec*                    PitchLFOTemplate;
  111.  
  112.         /* instrument overall loudness */
  113.         float                                        InstrOverallLoudness;
  114.  
  115.         /* list of template records describing each oscillator */
  116.         OscBankVectorRec*                TemplateArray;
  117.         /* this is the number of oscillators in the array */
  118.         long                                        NumOscillatorsInBank;
  119.     };
  120.  
  121.  
  122. typedef struct OscStateRec
  123.     {
  124.         /* this is a reference to the state object for this oscillator */
  125.         void*                                        StateReference;
  126.  
  127.         /* copy of the routine vectors */
  128.         OscBankVectorRec                Template;
  129.  
  130.         /* next oscillator in the list */
  131.         struct OscStateRec*            Next;
  132.     } OscStateRec;
  133.  
  134.  
  135. struct OscStateBankRec
  136.     {
  137.         /* what are we derived from */
  138.         OscBankTemplateRec*            BankTemplate;
  139.  
  140.         /* list of oscillators that this oscillator bank is comprised of */
  141.         OscStateRec*                        OscillatorList;
  142.  
  143.         /* this calculates the differential values for periodic pitch displacements */
  144.         LFOGenRec*                            PitchLFO;
  145.  
  146.         /* if this object ties to a note, then this is the note to tie to.  this is */
  147.         /* used for finding existing oscillators for tie continuations. */
  148.         struct NoteObjectRec*        TieToNote;
  149.  
  150.         /* portamento control parameters */
  151.         long                                        PortamentoCounter; /* 0 = done */
  152.         long                                        TotalPortamentoTicks;
  153.         float                                        InitialFrequency;
  154.         float                                        FinalFrequency;
  155.         float                                        CurrentFrequency;
  156.         /* True = portamento linear to Hertz; False = portamento linear to half-steps */
  157.         MyBoolean                                PortamentoHertz;
  158.  
  159.         /* various counters (in terms of envelope ticks) */
  160.         /* negative = expired */
  161.         long                                        Release1Countdown;
  162.         long                                        Release2Countdown;
  163.         long                                        Release3Countdown;
  164.         long                                        PitchLFOStartCountdown;
  165.  
  166.         /* next oscillator bank in the list */
  167.         struct OscStateBankRec*    Next;
  168.     };
  169.  
  170.  
  171. static OscStateRec*                            StateFreeList = NIL;
  172. static OscStateBankRec*                    StateBankFreeList = NIL;
  173.  
  174.  
  175. /* flush all cached oscillator state bank records */
  176. void                                    FlushCachedOscStateBankRecords(void)
  177.     {
  178.         while (StateBankFreeList != NIL)
  179.             {
  180.                 OscStateBankRec*        Temp;
  181.  
  182.                 Temp = StateBankFreeList;
  183.                 StateBankFreeList = StateBankFreeList->Next;
  184.                 ReleasePtr((char*)Temp);
  185.             }
  186.  
  187.         while (StateFreeList != NIL)
  188.             {
  189.                 OscStateRec*                Temp;
  190.  
  191.                 Temp = StateFreeList;
  192.                 StateFreeList = StateFreeList->Next;
  193.                 ReleasePtr((char*)Temp);
  194.             }
  195.     }
  196.  
  197.  
  198. #if DEBUG
  199. static void                    ValidateOscState(OscStateRec* State)
  200.     {
  201.         OscStateRec*            Scan;
  202.  
  203.         CheckPtrExistence(State);
  204.         Scan = StateFreeList;
  205.         while (Scan != NIL)
  206.             {
  207.                 if (Scan == State)
  208.                     {
  209.                         PRERR(ForceAbort,"ValidateOscState:  state object is on free list");
  210.                     }
  211.                 Scan = Scan->Next;
  212.             }
  213.     }
  214. #else
  215. #define ValidateOscState(x) ((void)0)
  216. #endif
  217.  
  218.  
  219. #if DEBUG
  220. static void                    ValidateOscStateBank(OscStateBankRec* StateBank)
  221.     {
  222.         OscStateBankRec*    Scan;
  223.  
  224.         CheckPtrExistence(StateBank);
  225.         Scan = StateBankFreeList;
  226.         while (Scan != NIL)
  227.             {
  228.                 if (Scan == StateBank)
  229.                     {
  230.                         PRERR(ForceAbort,"ValidateOscStateBank:  state bank object is on free list");
  231.                     }
  232.                 Scan = Scan->Next;
  233.             }
  234.     }
  235. #else
  236. #define ValidateOscStateBank(x) ((void)0)
  237. #endif
  238.  
  239.  
  240. /* construct an oscillator bank template record.  various parameters are passed in */
  241. /* which are needed for synthesis.  ParameterUpdator is the parameter information */
  242. /* record for the whole track of which this is a part. */
  243. OscBankTemplateRec*        NewOscBankTemplate(struct InstrumentRec* InstrumentDefinition,
  244.                                                 MyBoolean StereoFlag, LargeBCDType OverallVolumeScalingReciprocal,
  245.                                                 long SamplingRate, float EnvelopeRate, MyBoolean TimeInterp,
  246.                                                 MyBoolean WaveInterp, struct IncrParamUpdateRec* ParameterUpdator,
  247.                                                 ErrorDaemonRec* ErrorDaemon)
  248.     {
  249.         OscBankTemplateRec*    Template;
  250.         OscillatorListRec*    OscillatorListObject;
  251.         long                                Scan;
  252.  
  253.         CheckPtrExistence(InstrumentDefinition);
  254.         CheckPtrExistence(ParameterUpdator);
  255.         CheckPtrExistence(ErrorDaemon);
  256.  
  257.         Template = (OscBankTemplateRec*)AllocPtrCanFail(sizeof(OscBankTemplateRec),
  258.             "OscBankTemplateRec");
  259.         if (Template == NIL)
  260.             {
  261.              FailurePoint1:
  262.                 return NIL;
  263.             }
  264.  
  265.         /* the oscillator bank template contains all of the information needed for */
  266.         /* constructing oscillators as notes are to be executed. */
  267.         /* number of oscillators in a bank. */
  268.         OscillatorListObject = GetInstrumentOscillatorList(InstrumentDefinition);
  269.  
  270.         /* get LFO information */
  271.         Template->PitchLFOTemplate = GetInstrumentFrequencyLFOList(InstrumentDefinition);
  272.  
  273.         /* vector containing templates for all of the oscillators */
  274.         Template->TemplateArray = (OscBankVectorRec*)AllocPtrCanFail(
  275.             sizeof(OscBankVectorRec) * GetOscillatorListLength(OscillatorListObject),
  276.             "OscBankVectorRec");
  277.         if (Template->TemplateArray == NIL)
  278.             {
  279.              FailurePoint4:
  280.                 ReleasePtr((char*)Template);
  281.                 goto FailurePoint1;
  282.             }
  283.  
  284.         /* build entry for each oscillator */
  285.         Template->NumOscillatorsInBank = GetOscillatorListLength(OscillatorListObject);
  286.         for (Scan = 0; Scan < Template->NumOscillatorsInBank; Scan += 1)
  287.             {
  288.                 OscillatorRec*        Osc = GetOscillatorFromList(OscillatorListObject,Scan);
  289.  
  290.                 CheckPtrExistence(Osc);
  291.                 switch (OscillatorGetWhatKindItIs(Osc))
  292.                     {
  293.                         default:
  294.                             EXECUTE(PRERR(ForceAbort,"NewOscBankTemplate:  bad oscillator type"));
  295.                             break;
  296.                         case eOscillatorSampled:
  297.                             PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  298.                                 sizeof(Template->TemplateArray[Scan]));
  299.                             Template->TemplateArray[Scan].TemplateReference
  300.                                 = NewSampleTemplate(Osc,EnvelopeRate,SamplingRate,StereoFlag,
  301.                                 TimeInterp,WaveInterp,ErrorDaemon);
  302.                             if (Template->TemplateArray[Scan].TemplateReference == NIL)
  303.                                 {
  304.                                  FailurePoint5:
  305.                                     for (Scan = 0; Scan < Template->NumOscillatorsInBank; Scan += 1)
  306.                                         {
  307.                                             (*Template->TemplateArray[Scan]
  308.                                                 .DisposeTemplate)(Template->TemplateArray[
  309.                                                 Scan].TemplateReference);
  310.                                         }
  311.                                     goto FailurePoint4;
  312.                                 }
  313.                             Template->TemplateArray[Scan].UpdateEnvelopes
  314.                                 = (void (*)(void*))&UpdateSampleEnvelopes;
  315.                             Template->TemplateArray[Scan].DisposeState
  316.                                 = (void (*)(void*))&DisposeSampleState;
  317.                             Template->TemplateArray[Scan].DisposeTemplate
  318.                                 = (void (*)(void*))&DisposeSampleTemplate;
  319.                             Template->TemplateArray[Scan].NewState
  320.                                 = (void* (*)(void*,float,float,float,float,float,
  321.                                 float,float,long*,float,float,float,float,long))&NewSampleState;
  322.                             Template->TemplateArray[Scan].FixUpStatePreOrigin
  323.                                 = (void (*)(void*,long))&FixUpSampleStatePreOrigin;
  324.                             Template->TemplateArray[Scan].StateNewFrequency
  325.                                 = (void (*)(void*,float))&SampleStateNewFrequency;
  326.                             Template->TemplateArray[Scan].KeyUpSustain1
  327.                                 = (void (*)(void*))&SampleKeyUpSustain1;
  328.                             Template->TemplateArray[Scan].KeyUpSustain2
  329.                                 = (void (*)(void*))&SampleKeyUpSustain2;
  330.                             Template->TemplateArray[Scan].KeyUpSustain3
  331.                                 = (void (*)(void*))&SampleKeyUpSustain3;
  332.                             Template->TemplateArray[Scan].RestartState
  333.                                 = (void (*)(void*,float,float,float,float,float,float,float,
  334.                                 MyBoolean,float,float,float,float,long))&RestartSampleState;
  335.                             Template->TemplateArray[Scan].GenSamples
  336.                                 = (void (*)(void*,long,largefixedsigned*))&SampleGenSamples;
  337.                             Template->TemplateArray[Scan].IsItFinished
  338.                                 = (MyBoolean (*)(void*))&SampleIsItFinished;
  339.                             break;
  340.                         case eOscillatorWaveTable:
  341.                             PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  342.                                 sizeof(Template->TemplateArray[Scan]));
  343.                             Template->TemplateArray[Scan].TemplateReference
  344.                                 = NewWaveTableTemplate(Osc,EnvelopeRate,SamplingRate,StereoFlag,
  345.                                 TimeInterp,WaveInterp,ErrorDaemon);
  346.                             if (Template->TemplateArray[Scan].TemplateReference == NIL)
  347.                                 {
  348.                                     goto FailurePoint5;
  349.                                 }
  350.                             Template->TemplateArray[Scan].UpdateEnvelopes
  351.                                 = (void (*)(void*))&UpdateWaveTableEnvelopes;
  352.                             Template->TemplateArray[Scan].DisposeState
  353.                                 = (void (*)(void*))&DisposeWaveTableState;
  354.                             Template->TemplateArray[Scan].DisposeTemplate
  355.                                 = (void (*)(void*))&DisposeWaveTableTemplate;
  356.                             Template->TemplateArray[Scan].NewState
  357.                                 = (void* (*)(void*,float,float,float,float,float,
  358.                                 float,float,long*,float,float,float,float,long))&NewWaveTableState;
  359.                             Template->TemplateArray[Scan].FixUpStatePreOrigin
  360.                                 = (void (*)(void*,long))&FixUpWaveTableStatePreOrigin;
  361.                             Template->TemplateArray[Scan].StateNewFrequency
  362.                                 = (void (*)(void*,float))&WaveTableStateNewFrequency;
  363.                             Template->TemplateArray[Scan].KeyUpSustain1
  364.                                 = (void (*)(void*))&WaveTableKeyUpSustain1;
  365.                             Template->TemplateArray[Scan].KeyUpSustain2
  366.                                 = (void (*)(void*))&WaveTableKeyUpSustain2;
  367.                             Template->TemplateArray[Scan].KeyUpSustain3
  368.                                 = (void (*)(void*))&WaveTableKeyUpSustain3;
  369.                             Template->TemplateArray[Scan].RestartState
  370.                                 = (void (*)(void*,float,float,float,float,float,float,float,
  371.                                 MyBoolean,float,float,float,float,long))&RestartWaveTableState;
  372.                             Template->TemplateArray[Scan].GenSamples
  373.                                 = (void (*)(void*,long,largefixedsigned*))&WaveTableGenSamples;
  374.                             Template->TemplateArray[Scan].IsItFinished
  375.                                 = (MyBoolean (*)(void*))&WaveTableIsItFinished;
  376.                             break;
  377.                     }
  378.             }
  379.  
  380.         /* playback control parameters */
  381.         Template->StereoOutput = StereoFlag;
  382.         Template->OverallVolumeScalingFactor = 1.0 / LargeBCD2Single(OverallVolumeScalingReciprocal);
  383.         Template->SamplingRate = SamplingRate;
  384.         Template->EnvelopeUpdateRate = EnvelopeRate;
  385.         Template->TimeInterpolation = TimeInterp;
  386.         Template->WaveInterpolation = WaveInterp;
  387.  
  388.         Template->ParamUpdator = ParameterUpdator;
  389.  
  390.         Template->InstrOverallLoudness = GetInstrumentOverallLoudness(InstrumentDefinition);
  391.  
  392.         return Template;
  393.     }
  394.  
  395.  
  396. /* dispose of the template */
  397. void                                    DisposeOscBankTemplate(OscBankTemplateRec* Template)
  398.     {
  399.         long                                Scan;
  400.  
  401.         CheckPtrExistence(Template);
  402.  
  403.         for (Scan = 0; Scan < Template->NumOscillatorsInBank; Scan += 1)
  404.             {
  405.                 PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  406.                     sizeof(Template->TemplateArray[Scan]));
  407.                 (*Template->TemplateArray[Scan].DisposeTemplate)(Template->
  408.                     TemplateArray[Scan].TemplateReference);
  409.             }
  410.         ReleasePtr((char*)Template->TemplateArray);
  411.  
  412.         ReleasePtr((char*)Template);
  413.     }
  414.  
  415.  
  416. /* construct a new oscillator bank state object based on the note.  the note is */
  417. /* assumed to start "now" in terms of the parameters in the ParameterUpdator.  */
  418. /* the ScanningGapWidth is the number of envelope clock ticks in the current scanning */
  419. /* gap.  this is used to determine how far later than "now" in terms of the back */
  420. /* edge of the scanning gap (different from above) the osc bank should start playing. */
  421. /* *WhenToStartPlayingOut returns the number of envelope ticks after the back edge */
  422. /* of the scanning gap that the note should be started. */
  423. /*     <already played>       |    <scanning gap>     |    <not yet analyzed> */
  424. /*   time ---->    time ---->    time ---->    time ---->    time ---->   time ----> */
  425. /*                            ^A                      ^B     */
  426. /* point A is the back edge of the scanning gap.  as this edge moves forward in time, */
  427. /*   oscillator bank state objects are removed from the queue and playback is commenced */
  428. /*   for them. */
  429. /* point B is the front edge of the scanning gap.  as this edge moves forward in time, */
  430. /*   notes are extracted from the track and state bank objects are created for them. */
  431. /*   ParameterUpdator always reflects parameters at this point in time. */
  432. OscStateBankRec*            NewOscBankState(OscBankTemplateRec* Template,
  433.                                                 long* WhenToStartPlayingOut, struct NoteObjectRec* Note,
  434.                                                 float EnvelopeTicksPerDurationTick)
  435.     {
  436.         OscStateBankRec*        State;
  437.         long                                Scan;
  438.         FrozenNoteRec*            FrozenNote;
  439.         long                                StartPointAdjust;
  440.         long                                MaxOscillatorPreOriginTime;
  441.         OscStateRec*                OneState;
  442.         long                                ThisPreOriginTime;
  443.  
  444.         CheckPtrExistence(Template);
  445.         CheckPtrExistence(Note);
  446.  
  447.         if (StateBankFreeList != NIL)
  448.             {
  449.                 State = StateBankFreeList;
  450.                 StateBankFreeList = StateBankFreeList->Next;
  451.             }
  452.          else
  453.             {
  454.                 State = (OscStateBankRec*)AllocPtrCanFail(sizeof(OscStateBankRec),"OscStateBankRec");
  455.                 if (State == NIL)
  456.                     {
  457.                      FailurePoint1:
  458.                         return NIL;
  459.                     }
  460.             }
  461.         EXECUTE(State->Next = (OscStateBankRec*)0x81818181;)
  462.  
  463.         State->BankTemplate = Template;
  464.  
  465.         /* freeze the parameters */
  466.         FrozenNote = FixNoteParameters(Template->ParamUpdator,Note,&StartPointAdjust,
  467.             Template->OverallVolumeScalingFactor,EnvelopeTicksPerDurationTick);
  468.         if (FrozenNote == NIL)
  469.             {
  470.              FailurePoint2:
  471.                 State->Next = StateBankFreeList;
  472.                 StateBankFreeList = State;
  473.                 goto FailurePoint1;
  474.             }
  475.  
  476.         /* list of oscillators that this oscillator bank is comprised of */
  477.         State->OscillatorList = NIL;
  478.         MaxOscillatorPreOriginTime = 0;
  479.         for (Scan = 0; Scan < Template->NumOscillatorsInBank; Scan += 1)
  480.             {
  481.                 /* allocate the new record */
  482.                 if (StateFreeList != NIL)
  483.                     {
  484.                         OneState = StateFreeList;
  485.                         StateFreeList = StateFreeList->Next;
  486.                     }
  487.                  else
  488.                     {
  489.                         OneState = (OscStateRec*)AllocPtrCanFail(sizeof(OscStateRec),"OscStateRec");
  490.                         if (OneState == NIL)
  491.                             {
  492.                              FailurePoint3:
  493.                                 while (State->OscillatorList != NIL)
  494.                                     {
  495.                                         /* delink object */
  496.                                         OneState = State->OscillatorList;
  497.                                         State->OscillatorList = State->OscillatorList->Next;
  498.                                         /* dispose members */
  499.                                         (*OneState->Template.DisposeState)(OneState->StateReference);
  500.                                         /* stick on free list */
  501.                                         OneState->Next = StateFreeList;
  502.                                         StateFreeList = OneState;
  503.                                     }
  504.                                 goto FailurePoint2;
  505.                             }
  506.                     }
  507.  
  508.                 /* copy over the function vectors */
  509.                 PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  510.                     sizeof(Template->TemplateArray[Scan]));
  511.                 OneState->Template = Template->TemplateArray[Scan];
  512.  
  513.                 /* create the oscillator */
  514.                 OneState->StateReference = (OneState->Template.NewState)(
  515.                     OneState->Template.TemplateReference,FrozenNote->MultisampleFrequency,
  516.                     FrozenNote->Accent1,FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  517.                     FrozenNote->LoudnessAdjust * Template->InstrOverallLoudness,
  518.                     FrozenNote->HurryUpFactor,&ThisPreOriginTime,FrozenNote->StereoPosition,
  519.                     FrozenNote->NominalFrequency,FrozenNote->PitchDisplacementDepthLimit,
  520.                     FrozenNote->PitchDisplacementRateLimit,FrozenNote->PitchDisplacementStartPoint);
  521.                 if (OneState->StateReference == NIL)
  522.                     {
  523.                      FailurePoint3a:
  524.                         OneState->Next = StateFreeList;
  525.                         StateFreeList = OneState;
  526.                         goto FailurePoint3;
  527.                     }
  528.  
  529.                 if (ThisPreOriginTime > MaxOscillatorPreOriginTime)
  530.                     {
  531.                         MaxOscillatorPreOriginTime = ThisPreOriginTime;
  532.                     }
  533.  
  534.                 /* link it in */
  535.                 OneState->Next = State->OscillatorList;
  536.                 State->OscillatorList = OneState;
  537.             }
  538.  
  539.         /* this calculates the differential values for periodic pitch displacements */
  540.         State->PitchLFO = NewLFOGenerator(Template->PitchLFOTemplate,&ThisPreOriginTime,
  541.             FrozenNote->Accent1,FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  542.             FrozenNote->NominalFrequency,FrozenNote->HurryUpFactor,
  543.             Template->EnvelopeUpdateRate,FrozenNote->PitchDisplacementDepthLimit,
  544.             FrozenNote->PitchDisplacementRateLimit,FrozenNote->MultisampleFrequency);
  545.         if (State->PitchLFO == NIL)
  546.             {
  547.              FailurePoint4:
  548.                 goto FailurePoint3;
  549.             }
  550.         if (ThisPreOriginTime > MaxOscillatorPreOriginTime)
  551.             {
  552.                 MaxOscillatorPreOriginTime = ThisPreOriginTime;
  553.             }
  554.  
  555.         /* if this object ties to a note, then this is the note to tie to.  this is */
  556.         /* used for finding existing oscillators for tie continuations. */
  557.         State->TieToNote = Note->a.Note.Tie;
  558.  
  559.         /* portamento control parameters */
  560.         State->PortamentoCounter = 0;
  561.         State->CurrentFrequency = FrozenNote->NominalFrequency;
  562.  
  563.         /* fix up pre-origin times */
  564.         OneState = State->OscillatorList;
  565.         while (OneState != NIL)
  566.             {
  567.                 (*OneState->Template.FixUpStatePreOrigin)(OneState->StateReference,
  568.                     MaxOscillatorPreOriginTime);
  569.                 OneState = OneState->Next;
  570.             }
  571.         LFOGeneratorFixEnvelopeOrigins(State->PitchLFO,MaxOscillatorPreOriginTime);
  572.  
  573.         /* various counters (in terms of envelope ticks) */
  574.         if (State->TieToNote == NIL)
  575.             {
  576.                 State->Release1Countdown = FrozenNote->ReleasePoint1
  577.                     + MaxOscillatorPreOriginTime;
  578.                 State->Release2Countdown = FrozenNote->ReleasePoint2
  579.                     + MaxOscillatorPreOriginTime;
  580.                 State->Release3Countdown = FrozenNote->ReleasePoint3
  581.                     + MaxOscillatorPreOriginTime;
  582.             }
  583.          else
  584.             {
  585.                 /* for ties, only honor releases from start */
  586.                 if (FrozenNote->Release1FromStart)
  587.                     {
  588.                         State->Release1Countdown = FrozenNote->ReleasePoint1
  589.                             + MaxOscillatorPreOriginTime;
  590.                     }
  591.                  else
  592.                     {
  593.                         State->Release1Countdown = -1;
  594.                     }
  595.                 if (FrozenNote->Release2FromStart)
  596.                     {
  597.                         State->Release2Countdown = FrozenNote->ReleasePoint2
  598.                             + MaxOscillatorPreOriginTime;
  599.                     }
  600.                  else
  601.                     {
  602.                         State->Release2Countdown = -1;
  603.                     }
  604.                 if (FrozenNote->Release3FromStart)
  605.                     {
  606.                         State->Release3Countdown = FrozenNote->ReleasePoint3
  607.                             + MaxOscillatorPreOriginTime;
  608.                     }
  609.                  else
  610.                     {
  611.                         State->Release3Countdown = -1;
  612.                     }
  613.             }
  614.         State->PitchLFOStartCountdown = FrozenNote->PitchDisplacementStartPoint
  615.             /*+ MaxOscillatorPreOriginTime*/;
  616.         /* pre origin relationship must be preserved for pitch LFO trigger */
  617.  
  618.         /* clean up */
  619.         DisposeFrozenNote(FrozenNote);
  620.  
  621.         *WhenToStartPlayingOut = StartPointAdjust - MaxOscillatorPreOriginTime;
  622.  
  623.         return State;
  624.     }
  625.  
  626.  
  627. /* this is used for resetting a note for a tie */
  628. /* the FrozenNote object is NOT disposed */
  629. MyBoolean                            ResetOscBankState(OscStateBankRec* State,
  630.                                                 struct FrozenNoteRec* FrozenNote,
  631.                                                 float EnvelopeTicksPerDurationTick)
  632.     {
  633.         OscStateRec*                OneState;
  634.         MyBoolean                        RetriggerEnvelopes;
  635.  
  636.         CheckPtrExistence(State);
  637.         ValidateOscStateBank(State);
  638.         CheckPtrExistence(FrozenNote);
  639.  
  640.         RetriggerEnvelopes = ((FrozenNote->OriginalNote->Flags
  641.             & eRetriggerEnvelopesOnTieFlag) != 0);
  642.  
  643.         /* go through the oscillators and retrigger them */
  644.         OneState = State->OscillatorList;
  645.         while (OneState != NIL)
  646.             {
  647.                 (*OneState->Template.RestartState)(OneState->StateReference,
  648.                     FrozenNote->MultisampleFrequency,FrozenNote->Accent1,FrozenNote->Accent2,
  649.                     FrozenNote->Accent3,FrozenNote->Accent4,FrozenNote->LoudnessAdjust
  650.                     * State->BankTemplate->InstrOverallLoudness,FrozenNote->HurryUpFactor,
  651.                     RetriggerEnvelopes,FrozenNote->StereoPosition,
  652.                     FrozenNote->NominalFrequency,FrozenNote->PitchDisplacementDepthLimit,
  653.                     FrozenNote->PitchDisplacementRateLimit,FrozenNote->PitchDisplacementStartPoint);
  654.                 OneState = OneState->Next;
  655.             }
  656.  
  657.         LFOGeneratorRetriggerFromOrigin(State->PitchLFO,FrozenNote->Accent1,
  658.             FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  659.             FrozenNote->NominalFrequency,FrozenNote->HurryUpFactor,
  660.             FrozenNote->PitchDisplacementDepthLimit,
  661.             FrozenNote->PitchDisplacementRateLimit,RetriggerEnvelopes);
  662.  
  663.         /* if this object ties to a note, then this is the note to tie to.  this is */
  664.         /* used for finding existing oscillators for tie continuations. */
  665.         State->TieToNote = FrozenNote->OriginalNote->a.Note.Tie;
  666.  
  667.         /* portamento control parameters */
  668.         if (FrozenNote->PortamentoDuration > 0)
  669.             {
  670.                 State->PortamentoCounter = FrozenNote->PortamentoDuration;
  671.                 State->TotalPortamentoTicks = FrozenNote->PortamentoDuration;
  672.                 State->InitialFrequency = State->CurrentFrequency; /* save current pitch */
  673.                 State->FinalFrequency = FrozenNote->NominalFrequency;
  674.                 State->PortamentoHertz = ((FrozenNote->OriginalNote->Flags
  675.                     & ePortamentoHertzNotHalfsteps) != 0);
  676.             }
  677.          else
  678.             {
  679.                 State->PortamentoCounter = 0;
  680.                 State->CurrentFrequency = FrozenNote->NominalFrequency;
  681.             }
  682.  
  683.         /* various counters (in terms of envelope ticks) */
  684.         if (State->TieToNote == NIL)
  685.             {
  686.                 State->Release1Countdown = FrozenNote->ReleasePoint1;
  687.                 State->Release2Countdown = FrozenNote->ReleasePoint2;
  688.                 State->Release3Countdown = FrozenNote->ReleasePoint3;
  689.             }
  690.          else
  691.             {
  692.                 /* for ties, only honor releases from start */
  693.                 if (FrozenNote->Release1FromStart)
  694.                     {
  695.                         State->Release1Countdown = FrozenNote->ReleasePoint1;
  696.                     }
  697.                  else
  698.                     {
  699.                         State->Release1Countdown = -1;
  700.                     }
  701.                 if (FrozenNote->Release2FromStart)
  702.                     {
  703.                         State->Release2Countdown = FrozenNote->ReleasePoint2;
  704.                     }
  705.                  else
  706.                     {
  707.                         State->Release2Countdown = -1;
  708.                     }
  709.                 if (FrozenNote->Release3FromStart)
  710.                     {
  711.                         State->Release3Countdown = FrozenNote->ReleasePoint3;
  712.                     }
  713.                  else
  714.                     {
  715.                         State->Release3Countdown = -1;
  716.                     }
  717.             }
  718.         if (RetriggerEnvelopes)
  719.             {
  720.                 State->PitchLFOStartCountdown = FrozenNote->PitchDisplacementStartPoint;
  721.             }
  722.          else
  723.             {
  724.                 State->PitchLFOStartCountdown = -1;
  725.             }
  726.  
  727.         return True;
  728.     }
  729.  
  730.  
  731. /* get rid of a state bank */
  732. void                                    DisposeOscStateBank(OscStateBankRec* State)
  733.     {
  734.         OscStateRec*                OneStateScan;
  735.  
  736.         CheckPtrExistence(State);
  737.         ValidateOscStateBank(State);
  738.  
  739.         OneStateScan = State->OscillatorList;
  740.         while (OneStateScan != NIL)
  741.             {
  742.                 OscStateRec*                Temp;
  743.  
  744.                 (*OneStateScan->Template.DisposeState)(OneStateScan->StateReference);
  745.                 Temp = OneStateScan;
  746.                 OneStateScan = OneStateScan->Next;
  747.                 Temp->Next = StateFreeList;
  748.                 StateFreeList = Temp;
  749.             }
  750.  
  751.         DisposeLFOGenerator(State->PitchLFO);
  752.  
  753.         State->Next = StateBankFreeList;
  754.         StateBankFreeList = State;
  755.     }
  756.  
  757.  
  758. /* get the reference to the note that this bank ties to.  NIL if it doesn't */
  759. struct NoteObjectRec*    GetOscStateTieTarget(OscStateBankRec* State)
  760.     {
  761.         CheckPtrExistence(State);
  762.         ValidateOscStateBank(State);
  763.  
  764.         return State->TieToNote;
  765.     }
  766.  
  767.  
  768. /* perform one envelope clock cycle on a state bank.  this returns True if the */
  769. /* state bank is done and should be retired.  (it will return false if it is a */
  770. /* tie source.) */
  771. MyBoolean                            UpdateOscStateBank(OscStateBankRec* State, long NumFrames,
  772.                                                 largefixedsigned* OutputData)
  773.     {
  774.         OscStateRec*                OneStateScan;
  775.         MyBoolean                        OscillatorsRunning;
  776.         float                                Frequency;
  777.  
  778.         CheckPtrExistence(State);
  779.         ValidateOscStateBank(State);
  780.  
  781.         if (State->Release1Countdown >= 0)
  782.             {
  783.                 if (State->Release1Countdown == 0)
  784.                     {
  785.                         OneStateScan = State->OscillatorList;
  786.                         while (OneStateScan != NIL)
  787.                             {
  788.                                 (*OneStateScan->Template.KeyUpSustain1)(OneStateScan->StateReference);
  789.                                 OneStateScan = OneStateScan->Next;
  790.                             }
  791.                         LFOGeneratorKeyUpSustain1(State->PitchLFO);
  792.                     }
  793.                 State->Release1Countdown -= 1;
  794.             }
  795.  
  796.         if (State->Release2Countdown >= 0)
  797.             {
  798.                 if (State->Release2Countdown == 0)
  799.                     {
  800.                         OneStateScan = State->OscillatorList;
  801.                         while (OneStateScan != NIL)
  802.                             {
  803.                                 (*OneStateScan->Template.KeyUpSustain2)(OneStateScan->StateReference);
  804.                                 OneStateScan = OneStateScan->Next;
  805.                             }
  806.                         LFOGeneratorKeyUpSustain2(State->PitchLFO);
  807.                     }
  808.                 State->Release2Countdown -= 1;
  809.             }
  810.  
  811.         if (State->Release3Countdown >= 0)
  812.             {
  813.                 if (State->Release3Countdown == 0)
  814.                     {
  815.                         OneStateScan = State->OscillatorList;
  816.                         while (OneStateScan != NIL)
  817.                             {
  818.                                 (*OneStateScan->Template.KeyUpSustain3)(OneStateScan->StateReference);
  819.                                 OneStateScan = OneStateScan->Next;
  820.                             }
  821.                         LFOGeneratorKeyUpSustain3(State->PitchLFO);
  822.                     }
  823.                 State->Release3Countdown -= 1;
  824.             }
  825.  
  826.         /* perform portamento */
  827.         if (State->PortamentoCounter > 0)
  828.             {
  829.                 /* decrement is done before interpolation so that the final frequency */
  830.                 /* will actually be reached. */
  831.                 State->PortamentoCounter -= 1;
  832.                 if (State->PortamentoHertz)
  833.                     {
  834.                         /* this transition is linear, so it's easy to compute */
  835.                         /* L+F(R-L) */
  836.                         State->CurrentFrequency = State->InitialFrequency
  837.                             + ((float)(State->TotalPortamentoTicks
  838.                             - State->PortamentoCounter) / State->TotalPortamentoTicks)
  839.                             * (State->FinalFrequency - State->InitialFrequency);
  840.                     }
  841.                  else
  842.                     {
  843.                         /* this transition is log-linear, so it's a bit messier */
  844.                         State->CurrentFrequency = State->InitialFrequency * (float)FEXP(
  845.                             ((float)(State->TotalPortamentoTicks - State->PortamentoCounter)
  846.                             / State->TotalPortamentoTicks)
  847.                             * (((float)FLN(State->FinalFrequency) / (float)LOG2)
  848.                             - ((float)FLN(State->InitialFrequency) / (float)LOG2)) * LOG2);
  849.                     }
  850.             }
  851.  
  852.         /* update the pitch LFO modulation & figure out what the current pitch is */
  853.         if (State->PitchLFOStartCountdown > 0)
  854.             {
  855.                 State->PitchLFOStartCountdown -= 1;
  856.                 Frequency = State->CurrentFrequency;
  857.             }
  858.          else
  859.             {
  860.                 /* do some pitch stuff */
  861.                 Frequency = FastFixed2Float(LFOGenUpdateCycle(State->PitchLFO,
  862.                     Double2FastFixed(State->CurrentFrequency)));
  863.             }
  864.  
  865.         /* perform a cycle of resampling */
  866.         OscillatorsRunning = False;
  867.         OneStateScan = State->OscillatorList;
  868.         while (OneStateScan != NIL)
  869.             {
  870.                 (*OneStateScan->Template.StateNewFrequency)(OneStateScan->StateReference,Frequency);
  871.                 (*OneStateScan->Template.UpdateEnvelopes)(OneStateScan->StateReference);
  872.                 (*OneStateScan->Template.GenSamples)(OneStateScan->StateReference,NumFrames,OutputData);
  873.                 OscillatorsRunning = OscillatorsRunning || !(*OneStateScan->Template
  874.                     .IsItFinished)(OneStateScan->StateReference);
  875.                 OneStateScan = OneStateScan->Next;
  876.             }
  877.  
  878.         return !OscillatorsRunning;
  879.     }
  880.